#pragma once

#include <iostream>
#include "Data/LinkList/LinkList.h"


template<typename ValueType, uint8_t _TableSize=8>
class HashTable_Str
{
public:
	struct Pair
	{
		Pair(const char* inKey, const ValueType& inVal): key(inKey), value(inVal){}

		friend std::ostream& operator <<(std::ostream& os, const Pair& node)
		{
			os << node.key << ", " << node.value;

			return os;
		}
		
		const char* key;
		ValueType value;
	};
	
	HashTable_Str();
	~HashTable_Str();

	void Insert(const char* key, ValueType value);
	void Remove(const char* key);
	ValueType operator[](const char* key);

	void ShowTable();
private:
	// 计算哈希值
	uint8_t GetHashVal(const char* key) const;
private:
	uint8_t TableSize;
	LinkList<Pair>* Table;
};


template <typename ValueType, uint8_t _TableSize>
HashTable_Str<ValueType, _TableSize>::HashTable_Str()
	: TableSize(_TableSize)
{
	Table = new LinkList<Pair>[TableSize];
}

template <typename ValueType, uint8_t _TableSize>
HashTable_Str<ValueType, _TableSize>::~HashTable_Str()
{
	delete[] Table;
}

template <typename ValueType, uint8_t _TableSize>
uint8_t HashTable_Str<ValueType, _TableSize>::GetHashVal(const char* key) const
{
	// 使用取模的方式来计算哈希值
	const char* iter = key;
	unsigned int ascllVal = 0;
	while(*iter != '\0')
	{
		ascllVal += static_cast<unsigned>(*iter);
		++iter;
	}

	return ascllVal % TableSize;
}

template <typename ValueType, uint8_t _TableSize>
void HashTable_Str<ValueType, _TableSize>::Insert(const char* key, ValueType value)
{
	uint8_t hashIdx = GetHashVal(key);
	// 将键值对存入表中
	Pair node{key, value};
	Table[hashIdx].Insert(node);
}

template <typename ValueType, uint8_t _TableSize>
void HashTable_Str<ValueType, _TableSize>::Remove(const char* key)
{
	uint8_t hashIdx = GetHashVal(key);
	// 遍历链表，找到要删除的键值对的索引
	auto tableHead = Table[hashIdx].GetHead();
	int removedIdx = -1;
	while(tableHead)
	{
		++removedIdx;
		
		if(tableHead->data.key == key)
			break;
		
		tableHead = tableHead->next;
	}
	// 将键值对从链表中删除
	Table[hashIdx].Remove(removedIdx);
}

template <typename ValueType, uint8_t _TableSize>
ValueType HashTable_Str<ValueType, _TableSize>::operator[](const char* key)
{
	uint8_t hashIdx = GetHashVal(key);
	// 遍历链表，从中找到对应的键值对
	auto tableHead = Table[hashIdx].GetHead();
	while(tableHead)
	{
		if(tableHead->data.key == key)
			return tableHead->data.value;
		
		tableHead = tableHead->next;
	}

	return ValueType{};
}

template <typename ValueType, uint8_t _TableSize>
void HashTable_Str<ValueType, _TableSize>::ShowTable()
{
	for(int i = 0; i < TableSize; ++i)
	{
		std::cout << "Table[" << i << "] ";
		Table[i].ShowData();
		std::cout << "\n";
	};
}


